/**
 * 
 */
package com.lbh.music.ui;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import com.lbh.music.R;

/**
 * @author GHB
 * @Function 垂直SeekBar
 */
public class VerticalSeekBar extends View implements Runnable{

	private int minVal;
	private int maxVal;
	private int width;
	private int height;
	private int handlePos;
	private Bitmap bg;
	private Bitmap handler_on, handler_off;
	private boolean looping;
	private int stepPixels;				//移动的步长值，单位是像素点
	private boolean pressed;
	private int topRim, bottomRim;		//顶端和底端的空白
	private int currentVal;
	
	public interface OnValueChangedListener
	{
		void VauleChanged(int val);
	};
	private OnValueChangedListener valueChangeListener;
	
	public VerticalSeekBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		//变量初始化
		maxVal = 128;
		minVal = -128;
		looping = true;
		pressed = false;
		currentVal = 0;
		
		//图片读进来
		Bitmap tmpBg = BitmapFactory.decodeResource(context.getResources(),R.drawable.slider_bg);
		handler_on = BitmapFactory.decodeResource(getResources(),R.drawable.equalizer_thumb);
		handler_off = BitmapFactory.decodeResource(getResources(),R.drawable.equalizer_thumb);
		height = tmpBg.getHeight();
		width = Math.max(handler_on.getWidth(), tmpBg.getWidth());
		bg = Bitmap.createBitmap(width, height + handler_on.getHeight() / 2, Config.ARGB_8888);
		topRim = bottomRim = handler_on.getHeight() / 2;
		handlePos = height - handler_on.getHeight() / 2;
		
//		int[] tmpBuf = new int[bg.getWidth() * bg.getHeight()];
		int[] bgBuf = new int[width * height + 1];
		
//		tmpBg.getPixels(tmpBuf, 0, bg.getWidth(), 0, 0, bg.getWidth(), bg.getHeight());
		tmpBg.getPixels(bgBuf, (width - tmpBg.getWidth()) / 2, width, 0, 0, tmpBg.getWidth(), tmpBg.getHeight());
		bg.setPixels(bgBuf, 0, width, 0, 0, width, height);
		
		stepPixels = height / (maxVal - minVal);
		if(stepPixels < 1)
		{
			stepPixels = 1;
		}
		
		new Thread(this).start();
	}
	
	public VerticalSeekBar(Context context, AttributeSet attrs, int def) {
		super(context, attrs, def);
		// TODO Auto-generated constructor stub
	}

	@SuppressLint("DrawAllocation")
	@Override
	public void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		Paint mPaint = new Paint();
		mPaint.setAntiAlias(true);
		Bitmap handler;
		
		if(pressed)
		{
			handler = handler_on;
		}
		else
		{
			handler = handler_off;
		}
		
		int pos = handlePos - topRim;
//		canvas.setBitmap(bg);
		
		canvas.drawBitmap(bg, 0, 0, mPaint);
		canvas.drawBitmap(handler, 0, pos, mPaint);
		
//		canvas.drawBitmap(handler, 0, 300, mPaint);
		
		
		
//		canvas.rotate(270);
//		super.onDraw(canvas);
	}

	/* (non-Javadoc)
	 * @see android.widget.AbsSeekBar#onMeasure(int, int)
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec,
			int heightMeasureSpec) {
		// TODO Auto-generated method stub
//		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int w, h;
		
		w = GetMeasuredWidth(widthMeasureSpec);
		h = GetMeasuredHeight(heightMeasureSpec);
		
		width = w;
		height = h;
		
		setMeasuredDimension(w, h);
		LayoutParams l = getLayoutParams();
		l.height = h;
		l.width = w;
		setLayoutParams(l);
		
		this.getTop();
		this.getBottom();
		this.getLeft();
		this.getRight();
	}

	/* (non-Javadoc)
	 * @see android.widget.AbsSeekBar#onTouchEvent(android.view.MotionEvent)
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		boolean result = false;;
		
		int type = event.getAction();
		switch(type)
		{
			case MotionEvent.ACTION_DOWN:
				result = ProcTouchEvent_Down(event);
				pressed = true;
			break;
			
			case MotionEvent.ACTION_UP:
				pressed = false;
			break;
			
			case MotionEvent.ACTION_MOVE:
				result = ProcTouchEvent_Move(event);
//				Log.v(" ", "y="+Integer.toString((int) event.getY())+"rawY="+Integer.toString((int) event.getRawY()));
			break;
		}
		
		return result;
//		return super.onTouchEvent(event);
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(looping)
		{
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			postInvalidate();
		}
	}
	
	private int GetMeasuredWidth(int val)
	{
		int specMode;
		int specSize;
		int result;
		
		specMode = MeasureSpec.getMode(val);
		specSize = MeasureSpec.getSize(val);
		
		switch(specMode)
		{
			case MeasureSpec.AT_MOST:	result = width;						break;
			case MeasureSpec.EXACTLY:	result = Math.min(width, specSize);	break;
			case MeasureSpec.UNSPECIFIED:
			default:					result = width;						break;
		}
		
		return result;
	}
	
	private int GetMeasuredHeight(int val)
	{
		int specMode;
		int specSize;
		int result;
		
		specMode = MeasureSpec.getMode(val);
		specSize = MeasureSpec.getSize(val);
		
		switch(specMode)
		{
			case MeasureSpec.AT_MOST:	result = height;						break;
			case MeasureSpec.EXACTLY:	result = Math.min(height, specSize);	break;
			case MeasureSpec.UNSPECIFIED:
			default:					result = height;						break;
		}
		
		return result;
	}
	
	private boolean ProcTouchEvent_Down(MotionEvent event)
	{
		boolean result = true;
		
		int x = (int) event.getX();
		int y = (int) event.getY();
		
		if((x > width) || (x < 0) || (y < 0) || (y > height))	//在控件上下左右边沿之外，不予理睬
		{
			result = false;
			return result;
		}
		else if(y > height - bottomRim)
		{
			y = height - bottomRim;
		}
		else if(y < topRim)
		{
			y = topRim;
		}
		
		if(y != handlePos)
		{
			handlePos = y;
			CountValueAccd2HandlePos(handlePos);
		}
			
		return result;
	}
	
	private boolean ProcTouchEvent_Move(MotionEvent event)
	{
		boolean result = true;
		
		int x = (int) event.getX();
		int y = (int) event.getY();
		
		if((x > width) || (x < 0) || (y < 0) || (y > height))			//在控件左右边沿之外，不予理睬
		{
			result = false;
			return result;
		}
		else if(y > height - bottomRim)
		{
			y = height - bottomRim;
		}
		else if(y < topRim)
		{
			y = topRim;
		}
		
		if(y != handlePos)
		{
			handlePos = y;
			CountValueAccd2HandlePos(handlePos);
		}

		return result;
	}
	
	private void CountValueAccd2HandlePos(int pos)
	{
		int val;
		int range = maxVal - minVal;		//量程
		int length = height - topRim - bottomRim;	//
		float step = (float)range / (float)length;
		val = (int) ((length - (pos - topRim)) * step) + minVal;
		
		if((null != valueChangeListener) && (val != currentVal))
		{
			currentVal = val;
			valueChangeListener.VauleChanged(currentVal);
		}
	}
	
	public void SethandlePos(int pos, boolean setBackCall)
	{
		int p;
		if(maxVal < minVal)
		{
			if(pos > maxVal)
			{
				p = Math.min(pos, minVal);
			}
			else
			{
				p = Math.max(pos, maxVal);
			}
		}
		else
		{
			if(pos > minVal)
			{
				p = Math.min(pos, maxVal);
			}
			else
			{
				p = Math.max(pos, minVal);
			}
		}
		
		float scaleVal = (float)(p - minVal) / (float)(maxVal - minVal);
		float length = (float)(height - topRim - bottomRim) * (1 - scaleVal);
		
		handlePos = (int) (length + topRim);
		
		if((null != valueChangeListener) && (p != currentVal))
		{
			currentVal = p;
			if(setBackCall)
			{
				valueChangeListener.VauleChanged(currentVal);
			}
		}
	}
	
	public int GetCurrentVal()
	{
		return currentVal;
	}
	
	public void SetMaxMin(int max, int min)
	{
		if(max > min)
		{
			maxVal = max;
			minVal = min;
		}
		else
		{
			maxVal = min;
			minVal = max;
		}
		
		stepPixels = height / (maxVal - minVal);
		stepPixels = Math.max(stepPixels, 1);
	}

	public void Destroy()
	{
		looping = false;
	}
	
	public void SetOnValueChangedListener(OnValueChangedListener v)
	{
		if(null != v)
		{
			valueChangeListener = v;
		}
	}
	
	public void IncreaseVal()
	{
		if(currentVal < maxVal)
		{
			SethandlePos(currentVal + 1, true);
		}
	}
	
	public void DecreaseVal()
	{
		if(currentVal > minVal)
		{
			SethandlePos(currentVal - 1, true);
		}
	}
}
